#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "doge.h"

// Max row, max column, current char, word count, mistake count, score
int mr,mc,c,wordc,mis = 0,sc = 0,not_playing = 1; // is the game not running.
time_t time_ctr = 0,s = 0; // The time counter and the the game itself starts.
char **wordv; // The word list loaded from /usr/share/dict/words
bool typing=false;

// Phrases indicating a correct word.
static char *CORR_PHRASES[] = { "wow",
				"wow",
				"such smart",
				"such letters",
				"such spell",
				"many letters",
				"how smart",
				"good",
				"very typing",
				"how keyboard",
				"top doge" };

// Phrases indicating a mistyped letter.
static char *INCORR_PHRASES[] = { "o no",
				  "wat",
				  "pls",
				  "pls no",
				  "why",
				  "mabe next time",
				  "such learning",
				  "top kek",
				  "you can do it" };

void print_message(int col, bool correct)
{
    if (rand() % 2)
    {
        mvprintw(4,2,"________________");
        mvprintw(5,1,"/                \\");
        mvprintw(6,0,"<  ");
        attron(A_BOLD);
        printw("%-15s", correct ? \
                CORR_PHRASES[rand() % sizeof(CORR_PHRASES)/sizeof(CORR_PHRASES[0])] : \
                INCORR_PHRASES[rand() % sizeof(INCORR_PHRASES)/sizeof(INCORR_PHRASES[0])]);
        attroff(A_BOLD);
        printw(" |");
        mvprintw(7,1,"\\_________________/");
        move(10,col+3);
        refresh();
    }
}

// Loads the word file and counts the words. mallocs a char** to hold every word
// and mallocs each word in it.
// ERROR: Errors if the words file cannot be read and exits with exit(1).
void start_game(){
    move(3,0);
    clrtoeol();
    move(5,0);
    clrtoeol();

    getmaxyx(stdscr,mr,mc);
    FILE *f = fopen("words","r");
    char lb[128];
    int n;
    if (f == NULL)
    {
        clear();
        mvprintw(0,0,"ERROR:file:'words' not found");
        mvprintw(1,0,"Press any key to continue...");
        refresh();
        getch();
        endwin();
        exit(0);
    }
    for (wordc = 0;fgets(lb,128,f);wordc++);
    fseek(f,0,SEEK_SET);
    wordv = malloc(wordc * sizeof(char*));
    for (n = 0;fgets(lb,128,f);n++)
    {
        wordv[n] = strdup(lb);
    }
    time(&s);
    not_playing = 0;
    typing = true;
    play_word();
}

// Plays one word.
// Increments sc for every word you get correct.
// Increments c for every letter you get correct.
// Increments mis for every letter you get incorrect.
void play_word(){
    move(10,0);
    clrtoeol();
    int in,col = 0;
    char *word = wordv[rand() % wordc];
        int n;
    c = 0;
    attron(COLOR_PAIR(1));
    mvprintw(0,0,"APM: %.2f", ((double) sc / (time_ctr - s)));
    mvprintw(1,0,"TTT: %i",time_ctr - s);
    mvprintw(2,0,"ERR: %i",mis);
    mvprintw(3,0,"O K: %i",sc);
    attron(A_BOLD);
    mvprintw(9,2,"%s",word);
    mvprintw(10,0,"> ");
    attroff(A_BOLD);
    curs_set(1);
    while(1){
	if (word[c] == '\n'){
	    ++sc;
	    play_word();
	    break;
	}
	in = getch();
	switch(in){
	case 3:
	  for (n = 0;n < wordc;n++){
	      free(wordv[n]);
	  }
	  free(wordv);
	  pthread_cancel(time_thread);
	  endwin();
	  exit(0);
	  break;
	case 19:
	  play_word();
	  break;
	case KEY_RESIZE:
	    move(mr-1,mc-13);
	    clrtoeol();
	    endwin();
	    getmaxyx(stdscr,mr,mc);
	    move(10,2);
	    refresh();
	    continue;
	    break;
	case KEY_UP:
	case KEY_DOWN:
	case 10:
	    continue;
	    break;
	case KEY_BACKSPACE:
	case 330:
	case 127:
	    if (col == 0){
		continue;
	    }
	    --col;
	    printw("\b \b");
	    continue;
	    break;
	case 6:
	case KEY_RIGHT:
	    move(10,getcurx(stdscr)+1);
	    ++col;
	    continue;
	    break;
	case 2:
	case KEY_LEFT:
	    if (col == 0){
		continue;
	    }
	    move(10,getcurx(stdscr)-1);
	    --col;
	    continue;
	    break;
	}
	if (in == word[c] && col == c){
        printw("%c",in);
	    ++c;
        print_message(col, true);
	} else {
        attron(COLOR_PAIR(2));
        printw("%c", in);
        attroff(COLOR_PAIR(2));
        attron(COLOR_PAIR(1));
	    mvprintw(2,0,"ERR: %i",++mis);
	    move(10,col+3);
        print_message(col, false);
	}
	++col;
    }
}

// Hides the time if needed.
void show_time(){
    if (not_playing)
    {
        attron(A_INVIS);
    }
    move(1,0);
    clrtoeol();
    mvprintw(1,0,"TTT: %i",time_ctr - s);
    if (not_playing)
    {

        attroff(A_INVIS);
    }
}
